#include "app_lcd_main.h"
#include "lcd.h"
#include "stdio.h"

static const int pow[] = {10000, 1000, 100, 10, 1};
static const unsigned char PROGMEM image_ppbc_bits[] = {0x00, 0x00, 0x00, 0xc0, 0x03, 0xf0, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xf0, 0x00,
                                                        0x00, 0x00, 0xc0, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x0c, 0x0c, 0xff, 0x0f,
                                                        0xf0, 0xcf, 0x0c, 0x00, 0xff, 0x0f, 0xf0, 0xcf, 0x0c, 0x00, 0xc0, 0xcc, 0x0c,
                                                        0xf0, 0xcc, 0x00, 0xc0, 0xcc, 0x0c, 0xf0, 0xcc, 0x00, 0xff, 0x0f, 0xf0, 0xc0,
                                                        0xcc, 0x00, 0xff, 0x0f, 0xf0, 0xc0, 0xcc, 0x00, 0xc0, 0x0c, 0x00, 0xc0, 0xcc,
                                                        0x0c, 0xc0, 0x0c, 0x00, 0xc0, 0xcc, 0x0c, 0xc0, 0x0c, 0x00, 0xff, 0x03, 0xf0,
                                                        0xc0, 0x0c, 0x00, 0xff, 0x03, 0xf0};

static const unsigned char PROGMEM image_uscm_bits[] = {0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
                                                        0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
                                                        0x00, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00,
                                                        0xc3, 0x03, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0, 0xc3, 0x03, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0,
                                                        0xc3, 0x00, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0, 0xc3, 0x00, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0,
                                                        0xc3, 0x00, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0, 0xc3, 0x00, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0,
                                                        0xfc, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0, 0xfc, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0,
                                                        0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM image_nscm_bits[] = {0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xcf, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00, 0xcf, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00, 0xf0, 0xc3, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0, 0xf0, 0xc3, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0, 0xc0, 0xc0, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0, 0xc0, 0xc0, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0, 0xc0, 0xc0, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0, 0xc0, 0xc0, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0, 0xc0, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0, 0xc0, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0};

static const unsigned char PROGMEM image_mscm_bits[] = {0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf3, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00, 0xf3, 0x0c, 0x00, 0x03, 0x03, 0xf0, 0xf3, 0x00, 0xcc, 0xc3, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0, 0xcc, 0xc3, 0xf0, 0x0c, 0x0c, 0x00, 0xcc, 0xc0, 0xcc, 0xc0, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0, 0xcc, 0xc0, 0x0c, 0x30, 0x0c, 0x00, 0xcc, 0xc0, 0xc0, 0xc0, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0, 0xc0, 0xc0, 0x0c, 0xc0, 0x0c, 0x0c, 0xc0, 0xc0, 0xc0, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0, 0xc0, 0xcf, 0xf3, 0x00, 0x03, 0xf0, 0xc0, 0xc0};

static const unsigned char PROGMEM image_scm_bits[] = {0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x3f, 0x0f, 0x30, 0xc0, 0x00, 0x30, 0x3f, 0x0f, 0x30, 0x3f, 0x00, 0xc0, 0xc0, 0x0c, 0xcc, 0x3f, 0x00, 0xc0, 0xc0, 0x0c, 0xcc, 0x00, 0xc3, 0x00, 0xc0, 0x0c, 0xcc, 0x00, 0xc3, 0x00, 0xc0, 0x0c, 0xcc, 0x00, 0xcc, 0x00, 0xc0, 0xcc, 0x0c, 0x00, 0xcc, 0x00, 0xc0, 0xcc, 0x0c, 0xff, 0x30, 0x00, 0x3f, 0x0c, 0x0c, 0xff, 0x30, 0x00, 0x3f, 0x0c, 0x0c};

static const unsigned char PROGMEM image_C_bits[] = {0x3c, 0x0f, 0xc0, 0x3c, 0x0f, 0xc0, 0xc3, 0x30, 0x30, 0xc3, 0x30, 0x30, 0xc3, 0x30, 0x00, 0xc3, 0x30, 0x00, 0x3c, 0x30, 0x00, 0x3c, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x0f, 0xc0, 0x00, 0x0f, 0xc0};

void drawPoint(int ch, int num)
{
    static const int y0 = 80;
    static const int x0 = 52;

    // 静态变量记录每个通道上一次的点亮位置
    static int lastPos[2] = {-1, -1}; // 假设ch的范围是0-1

    // 确保ch在有效范围内
    if (ch < 0 || ch > 1)
        return;

    // 清除上一次的点（如果存在且不是全亮状态）
    if (lastPos[ch] != -1 && lastPos[ch] != 5)
    {
        tft.fillRect(x0 + 43 * lastPos[ch], y0 + 70 * ch, 7, 7, BLACK);
    }

    // 处理当前num
    if (num == 5)
    {
        // 点亮所有点
        for (int i = 0; i <= 4; i++)
        {
            tft.fillRect(x0 + 43 * i, y0 + 70 * ch, 7, 7, WHITE);
        }
    }
    else if (num >= 0 && num <= 4)
    {
        // 点亮指定点
        tft.fillRect(x0 + 43 * num, y0 + 70 * ch, 7, 7, WHITE);
    }

    // 更新记录
    lastPos[ch] = num;
}

void drawNumber(int num, int ch)
{
    static const int y0 = 28;
    static const int x0 = 22;
    static const int width = 43;
    static const int hight = 70;
    static int num_0 = -1;
    static int num_1 = -1;
    if (ch == 0 || ch == 1)
    {
        // if (ch == 0)
        // {
        //     tft.fillRect(15, 20, 210, 70, BLACK);
        // }
        // else
        // {
        //     tft.fillRect(15, 90, 210, 70, BLACK);
        // }
        if (num >= 0 && num <= 99999)
        {

            for (int i = 0; i < 5; i++)
            {
                int n = num / (pow[i]) % 10;
                int n_l;
                int num_l = ch ? num_1 : num_0;
                if (num_l == -1)
                {
                    n_l = 11;
                }
                else
                {
                    n_l = num_l / (pow[i]) % 10;
                }
                if (n_l != n)
                {
                    tft.drawNixie(x0 + width * i, y0 + hight * ch, 4, 2, WHITE, n, n_l);
                }
            }
            if(ch)
            {
                num_1 = num;
            }
            else
            {
                num_0 = num;
            }
        }
        else
        {
            for (int i = 0; i < 5; i++)
            {
                tft.drawNixie(x0 + width * i, y0 + hight * ch, 4, 2, WHITE, 10, 11);
            }
        }
    }
}

int _lg_num(float num)
{
    int n = (int)num;
    int i;
    if (n < 0)
        n = -n;
    for (i = 0; i < 12; i++)
    {
        if (n > 0)
        {
            n /= 10;
        }
        else
        {
            break;
        }
    }
    return i;
}

void drawErrorAB(int ch)
{
    drawNumber(-1, ch);
    drawPoint(ch, 5);
}

void Display_Line_AB(float number, cal_type_t type, int AB)
{
    switch (type)
    {
    case NO_DATA:
        drawErrorAB(AB);
        break;
    case CAL_TOC:
        // ppbc
        tft.fillRect(233, 58 + 70 * AB, 80, 32, 0); // 清除原有显示
        tft.drawBitmap(233, 75 + 70 * AB, image_ppbc_bits, 46, 14, 0xFFFF);
        if (number >= 0 && number < 100000)
        {
            int n = _lg_num(number);
            int m = (int)(number * pow[n - 1]);
            drawNumber(m, AB);
            drawPoint(AB, n - 1);
        }
        else
        {
            drawErrorAB(AB);
        }
        break;
    case CAL_temp:
        // 先不写
        break;
    case CAL_conductivity:
    {
        int n = _lg_num(number);
        if (n > 11)
        {
            drawErrorAB(AB);
        }
        else if (n > 6)
        {
            // S
            tft.fillRect(233, 58 + 70 * AB, 80, 32, 0);
            tft.drawBitmap(233, 60 + 70 * AB, image_scm_bits, 46, 14, 0xFFFF);
            int m = (int)(number / 1000000.0f * pow[n - 6]);
            drawNumber(m, AB);
            drawPoint(AB, n - 6);
        }
        else if (n > 3)
        {
            // ms
            tft.fillRect(233, 58 + 70 * AB, 80, 32, 0);
            tft.drawBitmap(233, 60 + 70 * AB, image_mscm_bits, 58, 14, 0xFFFF);
            int m = (int)(number / 1000.0f * pow[n - 4]);
            printf("%d\n", m);
            drawNumber(m, AB);
            drawPoint(AB, n - 4);
        }
        else if (n > 0)
        {
            // us
            tft.fillRect(233, 58 + 70 * AB, 80, 32, 0);
            tft.drawBitmap(233, 60 + 70 * AB, image_uscm_bits, 58, 16, 0xFFFF);
            int m = (int)(number * pow[n - 1]);
            drawNumber(m, AB);
            drawPoint(AB, n - 1);
        }
        else
        {
            // ns
            tft.fillRect(233, 58 + 70 * AB, 80, 32, 0);
            tft.drawBitmap(233, 60 + 70 * AB, image_nscm_bits, 58, 14, 0xFFFF);
            number *= 1000;
            n = _lg_num(number);
            if (n > 0)
            {
                int m = (int)(number * pow[n - 1]);
                drawNumber(m, AB);
                drawPoint(AB, n - 1);
            }
            else
            {
                drawNumber(0, AB);
            }
        }
    }
    break;
    default:
        break;
    }
}

// CD
static inline void Display_Line_CD_Clear(int CD)
{
    tft.fillRect(TFT_UI_START_X, TFT_UI_START_Y + TFT_TEXT_LENGTH * CD, 290, 20, 0);
}

static inline void DrawChar(int line, int list, char c)
{
    tft.setTextSize(TFT_TEXTSIZE);
    uint16_t y_pos;

    if (line == 0)
    {
        y_pos = TFT_UI_START_Y;
    }
    else if (line == 1)
    {
        y_pos = TFT_UI_START_Y + TFT_TEXT_LENGTH;
    }
    else
    {
        return;
    }
    tft.drawChar(c, TFT_UI_START_X + list * 12, y_pos, WHITE);
}

void drawErrorCD(int CD)
{
    for (int i = 0; i < 5; i++)
    {
        DrawChar(CD, i + 11, '_');
    }
}

void drawNumberCD(float number, int CD)
{
    int n = _lg_num(number);
    int m = (int)(number * pow[n - 1]);
    for (int i = 0; i < n; i++)
    {
        int c = m / (pow[i]) % 10;
        DrawChar(CD, i + 11, c + '0');
    }
    DrawChar(CD, n + 11, '.');
    if (n < 4)
    {
        for (int i = n; i < 4; i++)
        {
            int c = m / (pow[i]) % 10;
            DrawChar(CD, i + 12, c + '0');
        }
    }
}

void Display_Line_CD_CAL_conductivity(float number, int CD)
{
    int n = _lg_num(number);
    if (n > 11)
    {
        tft.drawBitmap(235, 181 + TFT_TEXT_LENGTH * CD, image_uscm_bits, 58, 16, 0xFFFF);
        drawErrorCD(CD);
    }
    else if (n > 6)
    {
        // S
        number /= 1000000.0f;
        tft.drawBitmap(235, 181 + TFT_TEXT_LENGTH * CD, image_scm_bits, 46, 14, 0xFFFF);
    }
    else if (n > 3)
    {
        // ms
        tft.drawBitmap(235, 181 + TFT_TEXT_LENGTH * CD, image_mscm_bits, 58, 14, 0xFFFF);
        number /= 1000.0f;
        drawNumberCD(number, CD);
    }
    else if (n > 0)
    {
        // us
        tft.drawBitmap(235, 181 + TFT_TEXT_LENGTH * CD, image_uscm_bits, 58, 16, 0xFFFF);
        drawNumberCD(number, CD);
    }
    else
    {
        // ns
        tft.drawBitmap(235, 181 + TFT_TEXT_LENGTH * CD, image_nscm_bits, 58, 14, 0xFFFF);
        number *= 1000.0f;
        n = _lg_num(number);
        if (n > 0)
        {
            drawNumberCD(number, CD);
        }
        else
        {
            DrawChar(CD, 15, '0');
        }
    }
}

void Display_Line_CD(float number, cal_type_t type, int CD)
{
    switch (type)
    {
    case NO_DATA:
        Display_Line_CD_Clear(CD);
        drawErrorCD(CD);
        break;
    case CAL_temp:
        Display_Line_CD_Clear(CD);
        tft.drawBitmap(235, 181 + CD * TFT_TEXT_LENGTH, image_C_bits, 20, 14, WHITE);
        if (number >= 0 && number < 100000)
        {
            drawNumberCD(number, CD);
        }
        else
        {
            drawErrorCD(CD);
        }
        break;
    case CAL_conductivity:
        Display_Line_CD_Clear(CD);
        Display_Line_CD_CAL_conductivity(number, CD);
        break;
    case CAL_conductivityU:
        Display_Line_CD_Clear(CD);
        Display_Line_CD_CAL_conductivity(number, CD);
        tft.drawChar('U', TFT_UI_START_X + 23 * 12 + 4, TFT_UI_START_Y + TFT_TEXT_LENGTH, WHITE);
        break;
    default:
        break;
    }
}
